package jpa.dao;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Query;

import jpa.model.Categoria;

import org.apache.log4j.Logger;

import jpa.factory.JPADAOFactory;

public class JPACategoriaDAO implements DAO<Categoria> {

	private static Logger logger = Logger.getLogger(JPACategoriaDAO.class);

	private EntityManager manager;

	private EntityTransaction transaction;

	public JPACategoriaDAO() {
		this.manager = this.openPersistence();
	}

	public <T> void closePersistence(T persistence) {
		if (this.manager != null && this.manager.isOpen()) {
			this.manager.close();
		}
	}

	@SuppressWarnings("unchecked")
	public <T> T openPersistence() {
		if (this.manager == null) {
			this.manager = ((EntityManagerFactory) JPADAOFactory.getInstance()
					.getFactory()).createEntityManager();
		}
		return (T) this.manager;
	}

	public <T extends Categoria> void atualizar(T categoria) {
		JPACategoriaDAO.logger.info("Atualizando a categoria: \n" + categoria);

		this.transaction = this.manager.getTransaction();

		if (categoria == null || categoria.getCategoria_id() == null) {
			throw new IllegalStateException("Categoria Inv�lido");
		}
		try {
			this.transaction.begin();
			if (this.manager.contains(categoria)) {
				this.manager.merge(categoria);
			}
			this.manager.flush();
			this.transaction.commit();
		} catch (Exception e) {
			if (this.transaction.isActive())
				this.transaction.rollback();
			throw new IllegalStateException("Problema ao Persistir o Objeto");
		}
	}

	@SuppressWarnings("unchecked")
	public <T extends Categoria> T recuperarPorId(Long id) {
		JPACategoriaDAO.logger.info("Recuperando a categoria por id: " + id);

		if (id == null || id <= 0) {
			throw new IllegalStateException("Identificador Inv�lido");
		}
		return (T) this.manager.find(Categoria.class, id);
	}

	@SuppressWarnings("unchecked")
	public <T extends Categoria> List<T> recuperarTodos() {
		JPACategoriaDAO.logger.info("Recuperando todas as categorias.");

		String consultaJPAQL = "select d from Categoria d";
		Query query = manager.createQuery(consultaJPAQL);
		List<Categoria> categorias = query.getResultList();
		return (List<T>) categorias;
	}

	@SuppressWarnings("unchecked")
	public <T extends Categoria> T remover(Long id) {
		JPACategoriaDAO.logger.info("Removendo a categoria com id: " + id);

		this.transaction = this.manager.getTransaction();
		Categoria categoria = this.recuperarPorId(id);
		if (categoria == null) {
			throw new IllegalStateException(
					"Categoria Inexistente para Remover");
		}
		try {
			this.transaction.begin();
			this.manager.remove(categoria);
			this.manager.flush();
			this.transaction.commit();
			return (T) categoria;
		} catch (Exception e) {
			if (this.transaction.isActive()) {
				this.transaction.rollback();
			}
			throw new IllegalStateException("Problema ao Persistir o Objeto");
		}
	}

	public <T extends Categoria> Long salvar(T categoria) {
		JPACategoriaDAO.logger.info("Salvando a categoria: \n" + categoria);

		this.transaction = this.manager.getTransaction();
		if (categoria == null || categoria.getNome() == null) {
			throw new IllegalStateException("Categoria Inv�lido");
		}
		try {
			this.transaction.begin();
			this.manager.persist(categoria);
			this.manager.flush();
			this.transaction.commit();
			return categoria.getCategoria_id().longValue();
		} catch (Exception e) {
			if (this.transaction.isActive()) {
				this.transaction.rollback();
			}
			e.printStackTrace();
			throw new IllegalStateException("Problema ao Persistir o Objeto");
		}
	}
}
